package io.gitee.buzizhi.tools;

import io.gitee.buzizhi.relation.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * @author :JSF
 * @date :2020/5/11 22:25
 * @desc :
 */
public class Base64Tool {

    /**
     * <li> 编码</li>
     * @param str 编码数据
     * @return
     */
    public static String encode(final String str) {
        if (StringTool.isBlank(str)) {
            throw new IllegalArgumentException("encode str can not null");
        }
        return Base64.encodeBase64String(str.getBytes());
    }

    /**
     * <li> 编码</li>
     * @param binaryData 二进制数据
     * @return
     */
    public static String encode(byte[] binaryData) {
        if(binaryData == null){
            throw new IllegalArgumentException("byte array can not null");
        }
        return Base64.encodeBase64String(binaryData);
    }

    /**
     * <li> 解码</li>
     * @param base64
     * @return
     */
    public static String decode(final String base64) {
        if (StringTool.isBlank(base64)) {
            throwBase64NullException();
        }
        String str = null;
        try {
            str = new String(Base64.decodeBase64(base64), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * <li> 解码为byte数组</li>
     * @param encodedText
     * @return
     */
    public static byte[] decodeBite(String encodedText) {
        if(StringTool.isBlank(encodedText)){
            throwBase64NullException();
        }
        byte[] bytes = Base64.decodeBase64(encodedText);
        return bytes;
    }

    /**
     * <li> 解码</li>
     * @param binaryData
     * @return
     */
    public static String decode(byte[] binaryData) {
        if(binaryData == null){
            throw new IllegalArgumentException("base 64 byte can not null");
        }
        String str = null;
        try {
            str = new String(Base64.decodeBase64(binaryData), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * <li> 判断是否base64过的原文，原理为解密再加密，得到原字符串则代表的是已加密过的</li>
     * @param base64
     * @return
     */
    public static boolean isBase64(final String base64) {
        if (StringTool.isBlank(base64)) {
            throwBase64NullException();
        }
        String de = decode(base64);
        String en = encode(de).replaceAll("[\\s*\t\n\r]", "");
        return base64.equals(en);
    }

    /**
     * <li> 判断不是base64过的原文</li>
     * @param base64
     * @return
     */
    public static boolean isNotBase64(final String base64) {
        return !isBase64(base64);
    }


    /**
     * <li> 得到一个base64文件的实际大小</li>
     * @param base64String
     * @return
     */
    public static long base64FileSize(String base64String) {
        if(StringTool.isBlank(base64String)){
            throwBase64NullException();
        }
        //1.获取base64字符串长度(不含data:audio/wav;base64,文件头)
        int size0 = base64String.length();

        //2.获取字符串的尾巴的最后10个字符，用于判断尾巴是否有等号，正常生成的base64文件'等号'不会超过4个
        String tail = base64String.substring(size0 - 10);

        //3.找到等号，把等号也去掉,(等号其实是空的意思,不能算在文件大小里面)
        int equalIndex = tail.indexOf("=");
        if (equalIndex > 0) {
            size0 = size0 - (10 - equalIndex);
        }
        //4.计算后得到的文件流大小，单位为字节
        return size0 - ((long) size0 / 8) * 2;
    }

    /**
     * <li> 文件转换为base64</li>
     * @param filePath 文件路径
     * @return
     */
    public static String fileToBase64(String filePath) {
        if(StringTool.isBlank(filePath)){
            throw new IllegalArgumentException("file path can not null");
        }
        InputStream in = null;
        byte[] data = null;
        // 返回Base64编码过的字节数组字符串
        String encode = null;
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        try {
            // 读取图片字节数组
            in = new FileInputStream(filePath);
            data = new byte[in.available()];
            in.read(data);
            encode = encoder.encode(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return encode;
    }

    /**
     * <li> base64转换为文件</li>
     * @param base64 base64串
     * @param filePath 文件路径
     * @return
     * @throws IOException
     */
    public static boolean base64ToFile(String base64, String filePath) throws IOException { // 对字节数组字符串进行Base64解码并生成图片
        if (StringTool.isBlank(base64)) // 图像数据为空
            throwBase64NullException();
        if(StringTool.isBlank(filePath)){
            throw new IllegalArgumentException("file path can not null");
        }
        BASE64Decoder decoder = new BASE64Decoder();
        OutputStream out = null;
        try {
            out = new FileOutputStream(filePath);
            // Base64解码
            byte[] b = decoder.decodeBuffer(base64);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            out.write(b);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
            return true;
        }
    }

    /**
     * <li> base64转换为图片</li>
     * @param base64String base64串
     * @param imgUrl 文件路径
     * @return
     * @throws IOException
     */
    public static boolean base64ToImage(String base64String,String imgUrl) throws IOException {
        if(StringTool.isBlank(base64String)){
            throwBase64NullException();
        }
        if(StringTool.isBlank(imgUrl)){
            throw new IllegalArgumentException("img url can not null");
        }
        byte[] bytes1 = base64ToBytes(base64String);
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
        BufferedImage bi1 = ImageIO.read(bais);
        File f1 = new File(imgUrl);
        String ext = imgUrl.substring(imgUrl.lastIndexOf(".") + 1,imgUrl.length());
        return ImageIO.write(bi1, ext, f1);
    }

    /**
     * <li> base64转换为byte数组</li>
     * @param base64String
     * @return
     */
    public static byte[] base64ToBytes(String base64String){
        if(StringTool.isBlank(base64String)){
            throwBase64NullException();
        }
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] bytes1 = decoder.decodeBuffer(base64String);
            return bytes1;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * <li> base64转换为输入流</li>
     * @param base64string
     * @return
     */
    public static InputStream base64ToInputStream(String base64string){
        if(StringTool.isBlank(base64string)){
            throwBase64NullException();
        }
        ByteArrayInputStream stream = null;
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bytes1 = decoder.decodeBuffer(base64string);
            stream = new ByteArrayInputStream(bytes1);
        } catch (Exception e) {
            // TODO: handle exception
        }
        return stream;
    }

    private static void throwBase64NullException(){
        throw new IllegalArgumentException("base 64 str can not null");
    }

    public static void main(String[] args) {
        String str = "a.33.jj";
        System.out.println(str.substring(str.lastIndexOf(".") + 1,str.length()));
    }

}
